package com.uraurora.crescent.util;

import com.uraurora.crescent.advanced.tree.impl.*;

import java.util.Objects;
import java.util.function.BinaryOperator;

public final class Trees {

    private Trees(){}

    public static <T> ArraySegmentTree<T> newArraySegmentTree(Iterable<? extends T> iterable,
                                                              BinaryOperator<T> updateMerge){
        return  new ArraySegmentTree(Objects.requireNonNull(iterable), updateMerge);
    }
    public static <T> ArraySegmentTree<T> newArraySegmentTree(T[] objects,
                                                              BinaryOperator<T> updateMerge){

        return new ArraySegmentTree(Objects.requireNonNull(objects), updateMerge);
    }

    public static <T> BinaryIndexedTree<T> newBinaryIndexedTree(Iterable<? extends T> iterable,
                                                                BinaryOperator<T> updateMerge,
                                                                BinaryOperator<T> queryMerge){
        return new BinaryIndexedTree(Objects.requireNonNull(iterable), updateMerge, queryMerge, 0L);
    }

    public static <T> BinaryIndexedTree<T> newBinaryIndexedTree(T[] objects,
                                                                BinaryOperator<T> updateMerge,
                                                                BinaryOperator<T> queryMerge){
        return new BinaryIndexedTree(Objects.requireNonNull(objects), updateMerge, queryMerge, 0L);
    }

    public static <T> BinaryIndexedTree<T> newBinaryIndexedTree(Iterable<T> iterable,
                                                                BinaryOperator<T> updateMerge,
                                                                BinaryOperator<T> queryMerge,
                                                                T defaultValue){
        return new BinaryIndexedTree<>(iterable, updateMerge, queryMerge, defaultValue);
    }

    public static <T> BinaryIndexedTree<T> newBinaryIndexedTree(T[] objects,
                                                                BinaryOperator<T> updateMerge,
                                                                BinaryOperator<T> queryMerge,
                                                                T defaultValue){
        return new BinaryIndexedTree<>(objects, updateMerge, queryMerge, defaultValue);
    }

    public static <T> DisjointSet<T> newDisjointSet(){
        return new DisjointSet<>();
    }

    public static Trie newTrie(){
        return new Trie();
    }

    public static SuffixTree newSuffixTree(){
        return new SuffixTree();
    }
}
